<?php

/***
 * Class CW_UrlSchemaClass contains methods necessary for URL schema implementation as well
 * as determining what application / controller to launch:
 ***/
class CW_UrlSchemaClass {

   /**
	* Core object registry
	* @access Private
	* @var Object
	*/
	private $Reg;


   /**
	* Default system application to launch
	* @access Public
	* @var String
	*/
	public $application;


   /**
	* Default system or application controller to launch
	* @access Public
	* @var String
	*/
	public $controller;


   /**
	* Contains URL parameters passed by query string
	* @access Private
	* @var Array
	*/
	private $url_values;


   // ! Constructor Method

   /**
	* Instantiates class and defines instance variables.
	*
	* @param Object $Reg Core object registry passed through by reference
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access public
	* @return Void
	*/
	public function __construct(&$Reg)
	{
		$this->Reg = &$Reg;

		$this->application = $Reg->Config->get('application', 'default_application');
		$this->controller = $Reg->Config->get('application', 'default_controller');

		$this->url_values = array();
	}


   // ! Mutator Method

   /**
	* Sets the default application.
	*
	* @param String $application Value for instance variable $this->application
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return True
	*/
	public function setApplication($application)
	{
		$this->application = $application;

		return true;
	}


   // ! Mutator Method

   /**
	* Sets the default controller.
	*
	* @param String $controller Value for instance variable $this->controller
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return True
	*/
	public function setController($controller)
	{
		$this->controller = $controller;

		return true;
	}


   // ! Accessor Method

   /**
	* Used to access the remaining segments of 'url_schema'.
	*
	* @param Integer $segment The
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Mixed
	*/
	public function getUrlSegment($segment)
	{
		return isset($this->url_values[$segment]) ? $this->url_values[$segment] : false;
	}


   // ! Executor Method

   /**
	* Takes a controller's URL schema and matches it against
	* the remaining url_values array.
	*
	* @param Array $parameters Child group to search.
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Array
	*/
	public function setControllerSchema($parameters)
	{
		/***
		 * Iterate through the current controller's URI schema
		 * parameters and match them up with what's left of our
		 * previous url_values:
		 ***/

		$parsed_schema = array();

		for($i = 0; $i < sizeof($parameters); $i++)
		{
			if(isset($this->url_values[$i]))
			{
				/***
				 * Does the current entry contain a validation pattern?
				 * If so, let's match it against the corresponding url_value.
				 * If it matches, add the value, if not, just add NULL:
				 ***/

				if(isset($parameters[$i]['pattern']))
				{
					if(preg_match($parameters[$i]['pattern'], $this->url_values[$i]))
					{
						$parsed_schema[$parameters[$i]['alias']] = $this->url_values[$i];
					}
					else
					{
						$parsed_schema[$parameters[$i]['alias']] = null;
					}
				}
				else
				{
					$parsed_schema[$parameters[$i]['alias']] = $this->url_values[$i];
				}
			}
		}


		/***
		 * All done! Let's return them:
		 ***/

		return $parsed_schema;
	}


   // ! Accessor Method

   /**
	* Searches $this->url_values for a matching application parameter
	* and validates its existence. Unless we're using shortcuts, the
	* FIRST URL parameter will ALWAYS refer to the name of an application.
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return String
	*/
	public function searchForApplication()
	{
		if(false == isset($this->url_values[0]))
		{
			return $this->application;
		}

		$supposed_application = $this->url_values[0];

		if($this->Reg->App->doesApplicationExist($supposed_application))
		{
			$this->application = $supposed_application;
		}

		array_shift($this->url_values);

		return $this->application;
	}


   // ! Accessor Method

   /**
	* Searches $this->url_values for a matching controller parameter
	* and validates its existence. Unless we're using shortcuts, the
	* SECOND URL parameter will ALWAYS refer to the name of an
	* existing application controller.
	*
	* @param None
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return String
	*/
	public function searchForController()
	{
		if(false == isset($this->url_values[0]))
		{
			return $this->controller;
		}

		$supposed_controller = $this->url_values[0];

		if($this->Reg->App->doesControllerExist($this->application, $this->url_values[0]))
		{
			$this->controller = $supposed_controller;
		}

		array_shift($this->url_values);

		return $this->controller;
	}


   // ! Executor Method

   /**
	* Formats the provided URL schema and preps it for parsing. This method also
	* searches for 'short cut' mapping files within all currently installed
	* applications and rewrites the current URL schema accordingly.
	*
	* @param String $schema Schema value passed via URL
	* @param String $delimiter What to use for splitting the string out into workable chunks
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Boolean
	*/
	public function prepUrlSchema($schema, $delimiter = '/')
	{
		foreach($this->collectShortCuts() as $pattern => $result)
		{
			if(preg_match("#^{$pattern}$#", $schema))
			{
				if(preg_match('#\$#', $result) && preg_match('#\(.+\)+#', $pattern))
				{
					$result = preg_replace("#^{$pattern}$#", $result, $schema);
				}

				$schema = $result;
			}
		}

		return $this->url_values = explode($delimiter, preg_replace('#' . preg_quote($delimiter) . '+$#i', '', $schema));
	}


   // ! Executor Method

   /**
	* Iterates across all applications, searching for shortcut maps. Once encounted, this method
	* will combine all shortcuts into one master array and return it for processing.
	*
	* @param none
	* @author Daniel Wilhelm II Murdoch <wilhelm.murdoch@gmail.com>
	* @since v 1.0.0
	* @access Public
	* @return Array
	*/
	public function collectShortCuts()
	{
		$every_shortcut = array();

		foreach($this->Reg->App->getAllApplications() as $application)
		{
			$shortcut_path = PATH_APPS . $application . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'shortcuts' . PHP_EXT;

			if(file_exists($shortcut_path))
			{
				require_once $shortcut_path;

				$every_shortcut = array_merge($every_shortcut, $shortcuts);
			}
		}

		return $every_shortcut;
	}
}

?>